/*
 The server is the main HTTP server that serves up the required files to run the web test.
 It executes get request to send files and any AJAX calls that are posted. This is a simple server
 that takes a requested page, processes it, converts it to a stream and sends it to the client.
 
 The server loads the config.json file and uses it's content as the settings for the server.
 
 Author: Charbel Choueiri
 Email: charbel.choueiri@live.ca
 
*/

/*
 This is the main ASP Node class that starts the server and handles the HTTP requests. 
 
 TODO: implement sessions
 TODO: implement script cashing
 TODO: implement file cashing.
 TODO: allow ability to control cashing from config file.
 TODO: implement a request and response to send to script context that contains all the information needed by the script to process HTML correctly.
 
 TODO: create a clean interface for the web server and for the ASP processor.
*/
function HTTPServer(configFilePath)
{
	var self = this;
	
	// Points the HTTP server that is created by the http packages.
	this.server = null;

	// Holds the entire server configurations. This is loaded from the config.json file.
	this.config = {}

	/*
	 This is a cash for the already executed files. It can be turned on or off. 
	 If in development mode then turn cash off so files can be fetched from the local file system directly. 
	 Otherwise turning cash on will greatly speed the processing of scripts and files.
	*/
	this.cash = {};
	
	/*
	 This is the ASP-Node.js object that handles all ASP requests. In the case of multiple
	 sessions, it is up to the server to store and restore the session for each request.
	 In the case of multi-domain hosting, a single ASP Node object can still handle all the requests. 
	*/
	this.aspNode = new ASPNode.create();

	/*
	 Loads the configuration file and starts the HTTP server listing onto the specified port.
	*/
	this.init = function()
	{
		// Load the configuration from the given file.
		this.config = JSON.parse(FS.readFileSync(configFilePath).toString());
		
		// Start the HTTP server according to the configuration, port and host.
		this.server = HTTP.createServer(this.request);
		this.server.listen(this.config.port, this.config.host);
		
		// Log to the console that the server has started.
		console.log('Started server (' + this.config.version + '): ' + this.config.host + ':' + this.config.port);
	};
	
	
	/*
	 The main HTTP request handler that reads the HTTP request and processes it.
	*/
	this.request = function(request, response)
	{	
		// Parse the URL to get the requested file. The URL is also used for the GET parameters.
		var url = URL.parse(request.url);
		
		// If there is no file specified then use the default index.
		if (url.pathname[url.pathname.length-1] == '/') url.pathname += self.config.index;

		// Reserved for future use.
		request.session = {};
		
		// Get the file name, extension and full path.
		request.file = {
				ext: Path.extname(url.pathname),
				name: Path.basename(url.pathname),
				root: self.config.root,
				path: Path.join(self.config.root, url.pathname) };

		// Check if the file exists. If it does not then return HTTP error.
		if (!FS.existsSync(request.file.path))
		{
			response.writeHead(404, {"Content-Type": "text/plain"});
			response.write("404 Not Found\n");
			response.end();
		}
		// If the file is an ASP file then pass it onto ASPNode.js to process.
		else if (request.file.ext == self.config.asp)
		{
			try
			{
				// Execute the asp file using ASP-Node.js
				self.aspNode.process(request, response);
			}
			catch (exception)
			{
				// If an exception occures then return it back to the client.
				response.writeHead(500, {"Content-Type": "text/plain"});
			    response.end(exception + "\n");
			}
		}

		// Otherwise stream the file content directly to the client.
		else self.handleFileRequest(request, response);
	};
	
	
	/*
	 Handles standard file requests that get sent directly to the client with no processing.
	 This expects given file to exist. 
	*/
	this.handleFileRequest = function(request, response)
	{
		// TODO: if cash is enabled then check if the cash already has this file.
		// TODO: If cash has the file then send the cashed content.
	
		// Get the file content and process it accordingly.
		FS.readFile(request.file.path, function (error, content)
		{
			// Handle any errors.
			if (error)
			{
				response.writeHead(500, {"Content-Type": "text/plain"});
			    response.end(error + "\n");
			}
			// If no errors then send the file content to the client.
			else
			{
				// Get the file content-type for given file.
				var contentType = (self.config['content-type'].hasOwnProperty(request.file.ext) ? self.config['content-type'][request.file.ext] : self.config['content-type']['default']);

				// Set the header, send the content, and end the response.
				response.writeHead(200, {'Content-Type': contentType});
				response.end(content);
			}
		});
	};


	// Call the constructor.
	this.init();
}

var FS = require('fs');
var VM = require('vm');
var Path = require('path');

// Global access to the HTTP server object.
var URL = require('url');
var HTTP = require('http');

var ASPNode = require('./ASPNode.js')

//Create the ASP node.js class. It will start it self.
var httpServer = new HTTPServer('config.json');
